using Crux.Core.Data;

namespace Crux.Core.NHibernate;

/// <summary>
/// IQueryRepositoryOfT
/// </summary>
public interface IQueryRepository<TContext>
    : IDisposableObservable, IAsyncDisposableObservable
    where TContext : NHibernateContext
{
    /// <summary>
    /// Context
    /// </summary>
    TContext Context { get; }
    /// <summary>
    /// 判断数据是否存在
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <returns></returns>
    bool Any<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> AnyAsync<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false, CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <returns></returns>
    T FirstOrDefault<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<T> FirstOrDefaultAsync<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false, CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <returns></returns>
    int Count<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> CountAsync<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false, CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <returns></returns>
    long LongCount<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="predicate"></param>
    /// <param name="ignoreFilter"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<long> LongCountAsync<T>(Expression<Func<T, bool>> predicate, bool ignoreFilter = false, CancellationToken cancellationToken = default) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TPrimary"></typeparam>
    /// <param name="primary"></param>
    /// <returns></returns>
    T Find<T, TPrimary>(TPrimary primary) where T : class, IGenericEntity<TPrimary>;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="id"></param>
    /// <returns></returns>
    T Find<T>(object id) where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="sql"></param>
    /// <returns></returns>
    ISQLQuery FromSqlRaw<TEntity>(string sql) where TEntity : class;
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="orderExpressions"></param>
    /// <param name="where"></param>
    /// <param name="option"></param>
    /// <returns></returns>
    Pageable<T> GetByPage<T>(
        IEnumerable<OrderExpression<T>> orderExpressions,
        Expression<Func<T, bool>>? where = null,
        PageOption option = default)
        where T : class;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="orderExpressions"></param>
    /// <param name="where"></param>
    /// <param name="option"></param>
    /// <param name="cancellationToken"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    Task<Pageable<T>> GetByPageAsync<T>(
        IEnumerable<OrderExpression<T>> orderExpressions,
        Expression<Func<T, bool>>? where = null,
        PageOption option = default,
        CancellationToken cancellationToken = default)
        where T : class;
    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="noTracking"></param>
    /// <param name="ignoreFilter"></param>
    /// <returns></returns>
    IQueryable<T> Query<T>(bool noTracking = true, bool ignoreFilter = false) where T : class;
}